﻿using System;
using System.Globalization;
using System.Security.Claims;
using System.Threading;          //引入多线程编程实现运行模式和设置模式的并行
using System.Threading.Tasks;
using System.Linq;

class Program
{
    private static AlarmPublisher _alarmPublisher;       //闹钟订阅器
    private static AppMode _currentMode = AppMode.Running;         //程序运行状态
    private static bool _isTickEnabled;        //判断滴答
    private static bool _isHandlingAlarm;     //判断响铃

    static void Main()
    {
        _alarmPublisher = new AlarmPublisher();          //订阅器
        _alarmPublisher.Tick += OnTick;            //加入滴答功能
        _alarmPublisher.AlarmTriggered += OnAlarmTriggered;        //加入响铃功能

        Console.WriteLine("程序已启动，按's'进入设置模式");

        while (true)
        {
            if (!_isHandlingAlarm && Console.KeyAvailable)
            {
                var key = Console.ReadKey(true);
                if (key.KeyChar == 's' && _currentMode == AppMode.Running)       //按“s”键进入设置模式
                {
                    EnterSettingsMode();
                }
            }
            Thread.Sleep(100);
        }
    }

    private static void OnTick(object sender, TickEventArgs e)      //滴答
    {
        if (_currentMode == AppMode.Running)
        {
            Console.WriteLine($"{e.CurrentTime:HH:mm:ss} 滴答");
        }
    }

    private static void OnAlarmTriggered(object sender, AlarmEventArgs e)    //响铃
    {
        _isHandlingAlarm = true;
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} 响铃开始，铃声：{e.Sound}");

        var cts = new CancellationTokenSource();      //线程管理，用于取消闹钟响铃操作
        var endTime = DateTime.Now.AddMinutes(2);        //结束时间

        // 处理用户输入
        Task.Run(() => HandleAlarmInput(e, cts));

        // 定时结束响铃
        Task.Run(() =>
        {
            while (DateTime.Now < endTime && !cts.IsCancellationRequested)
            {
                Thread.Sleep(1000);
            }
            if (!cts.IsCancellationRequested)
            {
                Console.WriteLine($"{DateTime.Now:HH:mm:ss} 响铃结束");
            }
            _isHandlingAlarm = false;
        });
    }

    private static void HandleAlarmInput(AlarmEventArgs e, CancellationTokenSource cts)    //闹钟响之后处理用户输入
    {
        Console.WriteLine("按'1'关闭闹钟\n按'2'10分钟后再次响铃");
        while (!cts.IsCancellationRequested)
        {
            if (Console.KeyAvailable)
            {
                var key = Console.ReadKey(true);
                if (key.KeyChar == '1')      //按1键：关闭闹钟
                {
                    e.TriggeredAlarm.IsActive = false;
                    Console.WriteLine("已关闭当前闹钟");
                    cts.Cancel();
                }
                else if (key.KeyChar == '2')       //按2键：10分钟后继续响铃
                {
                    var newAlarm = new Alarm         //设置10分钟后临时闹钟
                    {
                        Mode = RepeatMode.Once,
                        OnceDateTime = DateTime.Now.AddMinutes(10),
                        Sound = e.Sound,
                        IsActive = true
                    };
                    _alarmPublisher.AddAlarm(newAlarm); 
                    Console.WriteLine($"闹钟将于{newAlarm.OnceDateTime:HH:mm}再次响铃");
                    cts.Cancel();
                }
            }
            Thread.Sleep(100);
        }
    }

    //进入设置模式
    private static void EnterSettingsMode()
    {
        _currentMode = AppMode.Settings;
        Console.Clear();
        ShowSettingsMenu();
    }

    //展示设置模式
    private static void ShowSettingsMenu() 
    {
        while (_currentMode == AppMode.Settings)
        {
            Console.WriteLine($"\n当前模式：设置模式");
            Console.WriteLine($"滴答功能状态：{(_isTickEnabled ? "开启" : "关闭")}");
            Console.WriteLine($"当前闹钟数量：{_alarmPublisher.GetAlarms().Count()}");

            Console.WriteLine("\n1. 切换滴答状态");
            Console.WriteLine("2. 新增闹钟");
            Console.WriteLine("3. 返回运行模式");
            Console.Write("请选择操作：");

            var input = Console.ReadLine();
            switch (input)
            {
                case "1":    //开启/关闭滴答功能
                    _isTickEnabled = !_isTickEnabled;
                    _alarmPublisher.EnableTick(_isTickEnabled);
                    break;
                case "2":    //添加新的闹钟
                    AddNewAlarm();
                    break;
                case "3":   //返回运行模式
                    _currentMode = AppMode.Running;
                    Console.Clear();
                    return;
                default:
                    Console.WriteLine("无效输入");
                    break;
            }
        }
    }

    //添加新的闹钟
    private static void AddNewAlarm()
    {
        try      
        {
            var alarm = new Alarm();

            Console.Write("请输入时间（HH:mm）：");
            var timeInput = Console.ReadLine();
            if (!DateTime.TryParseExact(timeInput, "HH:mm", null, DateTimeStyles.None, out var time))
                throw new FormatException("时间格式错误");       //时间格式错误时及时抛出异常进行处理

            alarm.AlarmTime = time.TimeOfDay;

            Console.Write("请选择重复模式（1-一次性 2-每天 3-工作日 4-每周）：");       //设置闹钟重复模式
            var mode = Console.ReadLine() switch
            {
                "1" => RepeatMode.Once,
                "2" => RepeatMode.Daily,
                "3" => RepeatMode.Workdays,
                "4" => RepeatMode.Weekly,
                _ => throw new ArgumentException("无效模式")
            };

            alarm.Mode = mode;

            if (mode == RepeatMode.Once)       //不重复，设置响铃日期
            {
                Console.Write("请输入日期（yyyy-MM-dd）：");
                var dateInput = Console.ReadLine();
                if (!DateTime.TryParseExact(dateInput, "yyyy-MM-dd", null, DateTimeStyles.None, out var date))
                    throw new FormatException("日期格式错误");

                alarm.OnceDateTime = date.Date.Add(alarm.AlarmTime);
            }
            else if (mode == RepeatMode.Weekly)     //每周响铃一次，设置响铃星期
            {
                Console.Write("请输入星期几（1-7，1=周一）：");
                if (!int.TryParse(Console.ReadLine(), out int day) || day < 1 || day > 7)
                    throw new ArgumentException("无效星期");

                alarm.WeeklyDay = (DayOfWeek)(day % 7);
            }

            Console.Write("请输入铃声名称：");
            alarm.Sound = Console.ReadLine();

            _alarmPublisher.AddAlarm(alarm);
            Console.WriteLine("闹钟添加成功！");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"错误：{ex.Message}");        //进行异常处理
        }
    }
}
